<?php
/**
 * User: Titan
 * Date: Sep 28, 2010
 * Time: 5:29:23 PM
 */

/**
 * db_init()
 * 
 * Initialize the database for use, or check to see if it is installed
 * 
 * @return void
 */
function db_init(&$vars = array())
{
	global $db_url, $active_db;
	static $db_conn;

	if (empty($db_url) && (!defined('CONFIGURATION_MODE') || CONFIGURATION_MODE != 'INSTALL'))
	{
		include_once('./includes/install.inc');
		install_launch('install.php');
	}

	if (!isset($db_conn))
	{
		$db_conn = db_connect($db_url);
	}

	$active_db = $db_conn;
}

/**
 * db_connect()
 * 
 * establishes a connection to the database and if it exists, selects the database for use
 * 
 * @param mixed $url
 * @return
 */
function db_connect($url)
{
	$url = parse_url($url);

	$url['user'] = urldecode($url['user']);
	$url['pass'] = isset($url['pass']) ? urldecode($url['pass']) : '';
	$url['host'] = urldecode($url['host']);
	$url['path'] = urldecode($url['path']);
	if (!isset($url['port']))
	{
		$url['host'] = $url['host'] . ':' . $url['port'];
	}

	if (function_exists('mysql_connect'))
	{
		$connection = @mysql_connect($url['host'], $url['user'], $url['pass'], true, 2);
		$use_db = mysql_select_db(substr($url['path'], 1));
		if (!$connection || !$use_db)
		{
			if (defined('CONFIGURATION_MODE') && CONFIGURATION_MODE == 'INSTALL')
			{
				global $db_schema;
				$db_schema = ($use_db === false) ? substr($url['path'], 1) : false;

				return $connection;
			}

			return false;
		}

		mysql_query('SET NAMES "utf8"', $connection);
		return $connection;
	}
	else
	{
		system_set_message('You must enable the php_mysql module for this installation to work.');
		return false;
	}
}

/**
 * db_escape_string()
 * 
 * escape sql text to put it safely in the database
 * 
 * @param mixed $text
 * @return
 */
function db_escape_string($text)
{
	global $active_db;
	return mysql_real_escape_string($text, $active_db);
}

define('DB_QUERY_REPLACE_TOKEN', '/(%d|%s|%%|%f|%n)/');

/**
 * db_query()
 * 
 * Execute a SQL query
 * 
 * This function is useful because it takes away the need to worry about escaping strings, and
 * it allows making queries using a type of token replacement
 * 
 * ie. 
 * 
 * db_query("SELECT * FROM task WHERE description='%s'", 'SOME USER ENTERED TEXT');
 * 
 * @param mixed $sql
 * 		escaped MySQL query
 * @param mixed $args
 * 		parameters
 * @return
 * 		mysql_query resource
 */
function db_query($sql, $args = array())
{
	if (!is_array($args))
	{
		$args = array($args);
	}

	_db_replace_token_callback($args, true);
	$query = preg_replace_callback(DB_QUERY_REPLACE_TOKEN, '_db_replace_token_callback', $sql);

	return _db_query($query);
}

/**
 * _db_query()
 * 
 * helper for executing query
 * 
 * This function does the actual query calling and routing of MySQL errors
 * 
 * @param mixed $query
 * @return
 */
function _db_query($query)
{
	global $active_db;
	$result = mysql_query($query, $active_db);

	if (!mysql_errno($active_db))
	{
		return $result;
	}
	else
	{
		trigger_error(mysql_error($active_db) . "\nQUERY: " . $query, E_USER_WARNING);
		return false;
	}
}

/**
 * _db_replace_token_callback()
 * 
 * a helper function and a callback function to get rid of the percent escapes in SQL queries
 * 
 * @param mixed $match
 * @param bool $declare
 * @return
 */
function _db_replace_token_callback($match, $declare = false)
{
	static $args = null;
	if ($declare)
	{
		$args = $match;
		return;
	}

	switch ($match[1])
	{
		case '%d':
			// We must use type casting to int to convert FALSE/NULL/(TRUE?)
			$value = array_shift($args);
			$value = (int)$value;

			// We don't need db_escape_string as numbers are db-safe.
			return $value;
		case '%s':
			return db_escape_string(array_shift($args));
		case '%n':
			// Numeric values have arbitrary precision, so can't be treated as float.
			// is_numeric() allows hex values (0xFF), but they are not valid.
			$value = trim(array_shift($args));
			return is_numeric($value) && !preg_match('/x/i', $value) ? $value : '0';
		case '%%':
			return '%';
		case '%f':
			return (float)array_shift($args);
	}
}

/**
 * db_fetch_array()
 * 
 * convenience function
 * 
 * @param mixed $result
 * @return
 */
function db_fetch_array($result)
{
	return mysql_fetch_array($result, 1);
}

/**
 * db_result()
 * 
 * convenience function for returning a single value from a query
 * 
 * ie. 
 * 
 * db_result(db_query('SELECT name FROM developer WHERE did=1'));
 * 
 * @param mixed $result
 * @return
 */
function db_result($result)
{
	if ($result && mysql_num_rows($result) > 0)
	{
		$array = mysql_fetch_row($result);
		return $array[0];
	}
	
	return false;
}
